package com.xiaoq.logs.repository.impl;

import com.xiaoq.logs.entity.NginxLog;
import com.xiaoq.logs.repository.NginxLogRepository;
import org.apache.commons.lang3.StringUtils;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.aggregation.AggregationPipeline;
import org.mongodb.morphia.query.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.Iterator;
import java.util.List;

import static org.mongodb.morphia.aggregation.Group.*;

/**
 * Created by chenjh on 2018/2/11.
 */
@Repository
public class NginxLogRepositoryImpl implements NginxLogRepository {

    private static final Logger LOGGER = LoggerFactory.getLogger(NginxLogRepositoryImpl.class);

    @Autowired
    private Datastore datastore;

    @Override
    public boolean save(NginxLog nginxLog) {
        if(nginxLog!=null && StringUtils.isNotEmpty(nginxLog.getId())){
            datastore.save(nginxLog);
            return true;
        }

        return false;
    }

    @Override
    public List<NginxLog> findNginxLogList(String shopId, Long maxMillis, Long minMillis) {
        Query<NginxLog> nginxLogQuery = datastore.createQuery(NginxLog.class)
                .order("-createdAt")
                .limit(20);

        if(StringUtils.isNotEmpty(shopId)){
            nginxLogQuery.field("requestUrl").containsIgnoreCase(shopId);
        }
        if(maxMillis != null){
            nginxLogQuery.filter("createdAt <= ", maxMillis);
        }
        if(minMillis != null){
            nginxLogQuery.filter("createdAt > ", minMillis);
        }

        return nginxLogQuery.asList();
    }

    @Override
    public List<NginxLog> findNginxLogList(String shopId, String requestUrl, Double minRequestTime, Long beginMillis, Long endMillis) {
        Query<NginxLog> nginxLogQuery = datastore.createQuery(NginxLog.class)
                .order("-requestTime")
                .limit(50);

        if(StringUtils.isNotEmpty(shopId)){
            nginxLogQuery.field("requestUrl").containsIgnoreCase(shopId);
        }
        if(StringUtils.isNotEmpty(requestUrl)){
            nginxLogQuery.field("requestUrl").containsIgnoreCase(requestUrl);
        }
        if(minRequestTime != null) {
            nginxLogQuery.filter("requestTime > ", minRequestTime);
        }
        if(beginMillis != null){
            nginxLogQuery.filter("createdAt > ", beginMillis);
        }
        if(endMillis != null){
            nginxLogQuery.filter("createdAt < ", endMillis);
        }

        return nginxLogQuery.asList();
    }

    @Override
    public long findNginxLogCount(String shopId, Long maxMillis, Long minMillis) {
        Query<NginxLog> nginxLogQuery = datastore.createQuery(NginxLog.class);

        if(StringUtils.isNotEmpty(shopId)){
            nginxLogQuery.field("requestUrl").containsIgnoreCase(shopId);
        }
        if(maxMillis != null){
            nginxLogQuery.filter("createdAt <= ", maxMillis);
        }
        if(minMillis != null){
            nginxLogQuery.filter("createdAt > ", minMillis);
        }

        return nginxLogQuery.count();
    }

    @Override
    public long findNginxLogCountUv(String shopId, Long maxMillis, Long minMillis) {
        long count = 0;
        Query<NginxLog> nginxLogQuery = datastore.createQuery(NginxLog.class);
        if(StringUtils.isNotEmpty(shopId)){
            nginxLogQuery.field("requestUrl").containsIgnoreCase(shopId);
        }
        if(maxMillis != null){
            nginxLogQuery.filter("createdAt <= ", maxMillis);
        }
        if(minMillis != null){
            nginxLogQuery.filter("createdAt > ", minMillis);
        }

        AggregationPipeline pipeline = datastore.createAggregation(NginxLog.class)
                .match(nginxLogQuery)
                .group(id(grouping("userId"),grouping("requestUrl")),   //以 userId,requestUrl 分组
                        grouping("requestUrl",first("requestUrl")),
                        grouping("userId",first("userId"))
//                        grouping("count",new Accumulator("$sum", 1))
                );

        Iterator<NginxLog> iterator = pipeline.aggregate(NginxLog.class);

        while (iterator.hasNext()) {
            NginxLog nginxLog = iterator.next();
            count ++;
        }

        return count;
    }
}
